﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace igflow
{
    
    public class Batch
    {
        int vCount;
        int iCount;
        public BasicEffect effect;
        public VertexDeclaration vertexDeclaration;
        Texture2D texture;

        public Batch(string tex)
        {
            effect = new BasicEffect(World.Graphics.GraphicsDevice, null);
            texture = World.contentManager.Load<Texture2D>(tex);
            effect.VertexColorEnabled = true;
            effect.TextureEnabled = true;
            vertexDeclaration = new VertexDeclaration(World.Graphics.GraphicsDevice, VertexPositionColorTexture.VertexElements);
        }
        VertexPositionColorTexture[] Vertices = new VertexPositionColorTexture[4000];
        short[] Indexes = new short[6000];
        public void AddVertex( VertexPositionColorTexture v)
        {
            if ( vCount < 4000 )
            {
                Vertices[vCount] = v;
                vCount += 1;
            }
        }

        public void AddIndex(int i)
        {
            if ( iCount < 6000)
            {
                Indexes[iCount] = (short)i;
                iCount += 1;
            }
        }

        internal int GetVCount()
        {
            return vCount;
        }

        internal VertexPositionColorTexture[] GetVertices()
        {
            return Vertices;
        }

        internal short[] GetIndexes()
        {
            return Indexes;
        }

        internal void Reset()
        {
            vCount = 0;
            iCount = 0;
        }
    }

    public static class Renderer
    {
        static Dictionary<string, Batch> Batches = new Dictionary<string,Batch>();
        public static void Render()
        {
            foreach (KeyValuePair<string,Batch> i in Batches)
            {
                Batch batch = i.Value;

                    // stick the mesh in the batch;
                
                    BasicEffect currentEffect = batch.effect;
                    currentEffect.GraphicsDevice.VertexDeclaration = batch.vertexDeclaration;
                    currentEffect.View = CameraManager.CurrentCamera.View;
                    currentEffect.Projection = CameraManager.CurrentCamera.Projection;
                    currentEffect.World = Matrix.Identity;
                    currentEffect.Begin();
                    foreach (EffectPass pass in currentEffect.CurrentTechnique.Passes)
                    {
                        pass.Begin();

                        World.Graphics.GraphicsDevice.DrawUserIndexedPrimitives
                           <VertexPositionColorTexture>(
                           PrimitiveType.TriangleList,
                           batch.GetVertices(), 0, batch.GetVertices().Length,
                           batch.GetIndexes(), 0, batch.GetIndexes().Length / 3);

                        pass.End();
                    }
                    currentEffect.End();
            }

        }

        public static void End()
        {
            // reset batches
            foreach( KeyValuePair<string,Batch> i in Batches )
            {
                i.Value.Reset();
            }
        }

        internal static void Draw(Mesh mesh)
        {

                if (mesh.Textures != null)
                {
                    //effect.Texture = mesh.Textures[0];
                    //effect.TextureEnabled = true;
                    //effect.GraphicsDevice.RenderState.AlphaBlendEnable = true;
                   // effect.GraphicsDevice.RenderState.AlphaBlendEnable = true;
                    //effect.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
                   // effect.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
                }
                //effect.VertexColorEnabled = true;
                //effect.Projection = World.currentCamera.Projection;
                //effect.View = gameObject.WorldMatrix * World.currentCamera.View;
                //World.Graphics.GraphicsDevice.RenderState.CullMode = CullMode.None;
                //World.Graphics.GraphicsDevice.RenderState.FillMode = FillMode.WireFrame;
                //World.Graphics.GraphicsDevice.VertexDeclaration = mesh.VertexDeclaration;

                /*
                currentEffect.CurrentTechnique = currentEffect.Techniques["Simplest"];
                currentEffect.Parameters["xModelViewProjection"].SetValue(gameObject.WorldMatrix * World.currentCamera.View * World.currentCamera.Projection);

                t += 0.016f * dir;
                if (t >= 1.0f)
                {
                    dir *= -1;
                }

                if (t <= 0.0f)
                {
                    dir *= -1;
                }

                currentEffect.Parameters["pos"].SetValue(t);
                */
                Batch currentBatch = GetBatch("TextureName");
                int precount = currentBatch.GetVCount();
                for( int A = 0 ; A < mesh.Vertices.Length ; ++A)
                {
                    //vCount + 
                    currentBatch.AddVertex(mesh.Vertices[A]);
                }
                
                for (int B = 0; B < mesh.Indexes.Length ; ++B)
                {
                    currentBatch.AddIndex(precount + mesh.Indexes[B]);
                }
        }

        internal static void Draw(Mesh mesh, GameObject.igGameObject gameObject)
        {
            string texture = "";
            if (mesh.Textures != null)
            {
                texture = mesh.Textures[0].Name;
            }
            Batch currentBatch = GetBatch(texture);
            if (currentBatch != null)
            {
                int precount = currentBatch.GetVCount();
                for (int A = 0; A < mesh.Vertices.Length; ++A)
                {
                    //vCount + 
                    VertexPositionColorTexture v = mesh.Vertices[A];
                    v.Position = Vector3.Transform(mesh.Vertices[A].Position, gameObject.WorldMatrix);
                    currentBatch.AddVertex(v);
                }

                for (int B = 0; B < mesh.Indexes.Length; ++B)
                {
                    currentBatch.AddIndex(precount + mesh.Indexes[B]);
                }
            }
        }

        private static Batch GetBatch(string p)
        {
            if (p != "")
            {
                if (Batches.ContainsKey(p))
                {
                    return Batches[p];
                }
                else
                {
                    Batch n = new Batch(p);
                    Batches.Add(p, n);
                    return n;
                }
            }
            return null;
        }
    }
}
